<?php
class SfUser extends SJKObj {
    const LOGIN_STATUS_OK=1;
    const LOGIN_STATUS_WRONG_PASSWORD=2;
    const LOGIN_STATUS_LOGIN_NOT_EXISTS=3;

    const STATUS_ADD_OK=4;
    const STATUS_LOGIN_EXISTS=5;
    const STATUS_ADD_FAIL=6;
    const STATUS_INVALID_LOGIN=7;

    const LOGIN_ATTR='login_name';
    private $uniqueAttrs=array('login_name');

    private $mTable;
    private $mTableAttr;
    function __construct() {
        global $bbsjk;
        $this->sjk=$bbsjk;
        $this->mTable='cm_user';
        $this->mTableAttr='cm_user_attr';
    }

    function isLogin() {
        @session_start();
        if (empty($_SESSION['is_login'])) {
            return false;
        } else {
            return (bool)$_SESSION['is_login'];
        }
    }

    function isAdmin() {
        @session_start();
        return @$_SESSION['is_admin'];
    }

    function tryLogin($login,$pass) {
        @session_start();
        if ($login=='admin') {
            if ($pass==cg('admin_password')) {
                $_SESSION['is_login']=true;
                $_SESSION['is_admin']=true;
                $_SESSION['login_name']='admin';
                return self::LOGIN_STATUS_OK;
            } else {
                return self::LOGIN_STATUS_WRONG_PASSWORD;
            }
        }

        $status=0;

        if ($row=$this->getByLogin($login)) {
            if ($row['pass']!=self::digestPassword($pass,$row['digestkey'])) {
                $status=self::LOGIN_STATUS_WRONG_PASSWORD;
            } else {
                $_SESSION['is_admin']=false;
                $_SESSION['is_login']=true;
                $status=self::LOGIN_STATUS_OK;
                foreach ($row as $field => $value) {
                    if ($field=='pass') {
                        continue;
                    }
                    $_SESSION[$field]=$value;
                }
            }
        } else {
            $status=self::LOGIN_STATUS_LOGIN_NOT_EXISTS;
        }
        return $status;
    }
    function logout() {
        $_SESSION['is_login']=false;
        unset($_SESSION['is_login']);
    }
    function add($pass,$attrs) {
        $login=trim($attrs[self::LOGIN_ATTR]);
        if (empty($login)) {
            return self::STATUS_INVALID_LOGIN;
        }
        if ($this->getByLogin($login)) {
            return self::STATUS_LOGIN_EXISTS;
        }
        $this->sjk->initSql('INSERT INTO '.$this->mTable.' #1');
        $digestkey=self::generateDigestKey();
        $arr=array(
                'pass'=>self::digestPassword($pass,$digestkey),
                'digestkey'=>$digestkey,
                'register_time'=>time(),
                'register_ip'=>Remoter::ip(),
        );
        $this->sjk->setInsertArray(1,$arr);

        if ($this->sjk->query()) {
            $uid=$this->sjk->getInsertId();
            foreach ($attrs as $k=>$v) {
                $this->updateAttr($uid, $k, $v);
            }
            return self::STATUS_ADD_OK;
        } else {
            return self::STATUS_ADD_FAIL;
        }
    }

    function getByLogin($login) {
        $this->table=$this->mTableAttr;
        $uid=$this->selectOne(array('key'=>self::LOGIN_ATTR,'value'=>$login),'uid');
        if (!$uid) {
            return false;
        }
        return $this->getByUid($uid);
    }
    function getByUid($uid) {
        $this->table=$this->mTableAttr;
        $user_info=array();
        $rows=$this->selectAll(array('uid'=>$uid));
        foreach ($rows as $row) {
            $user_info[$row['key']]=$row['value'];
        }
        $this->table=$this->mTable;
        $row=$this->selectRow(array('uid'=>$uid));
        $user_info['uid']=$row['uid'];
        $user_info['pass']=$row['pass'];
        $user_info['digestkey']=$row['digestkey'];
        return $user_info;
    }

    function updateAttr($uid, $attr_key, $attr_value) {
        if ($this->getAttr($uid, $attr_key)!==false) {
            $this->sjk->initSql('UPDATE '.$this->mTableAttr.' 
                    SET `value`=#3 WHERE `uid`=#1 AND `key`=#2 LIMIT 1');
            $this->sjk->setInt(1,$uid);
            $this->sjk->setString(2,$attr_key);
            $this->sjk->setString(3,$attr_value);
            return $this->sjk->query();
        } else {
            if (in_array($attr_key, $this->uniqueAttrs)
                && $this->getAttrWithoutUid($attr_key, $attr_value)
                ) {
                return false;
            }
            $data_arr=array(
                'uid'=>$uid,
                'key'=>$attr_key,
                'value'=>$attr_value,
            ); 
            $this->sjk->initSql('INSERT INTO '.$this->mTableAttr.'  #1');
            $this->sjk->setInsertArray(1, $data_arr);
            return $this->sjk->query();
        }
    }

    function getAttr($uid, $attr_key) {
        $this->sjk->initSql('SELECT value FROM '.$this->mTableAttr.' WHERE uid=#1 AND `key`=#2 LIMIT 1');
        $this->sjk->setInt(1,$uid);
        $this->sjk->setString(2,$attr_key);
        $rs=$this->sjk->query();
        if ($row=$rs->fetch()) {
            return $row['value'];
        }
        return false;
    }
    function getAttrWithoutUid($attr_key, $attr_value) {
        $this->sjk->initSql('SELECT value FROM '.$this->mTableAttr.' 
                             WHERE `key`=#2 AND `value`=#3 LIMIT 1');
        $this->sjk->setString(2,$attr_key);
        $this->sjk->setString(3,$attr_value);
        $rs=$this->sjk->query();
        if ($row=$rs->fetch()) {
            return $row;
        }
        return false;
    }
    function getSome($offset, $limit, $wheres=array()) {
        $this->sjk->initSql('SELECT uid FROM '.$this->mTable.$this->buildWhere($wheres).
                ' ORDER BY register_time LIMIT '.$offset.','.$limit);
        $rs=$this->sjk->query();
        $users=array();
        foreach ($rs as $row) {
            $users[]=$this->getByUid($row['uid']);
        }
        return $users;
    }
    function searchCount($word) {
    $this->sjk->initSql('SELECT count(distinct uid) as c FROM '.$this->mTableAttr.
                        " WHERE ".
                        " (`key`='login_name' AND `value` like #1)".
                        " OR (`key`='first_name' AND `value` like #1)".
                        " OR (`key`='first_name' AND `value` like #1)".
                        " OR (`key`='email' AND `value` like #1)".
                        " OR (`key`='host' AND `value` like #1)"
        );
        $this->sjk->setString(1, '%'.$word.'%');
        $rs=$this->sjk->query();
        $row=$rs->fetch(); 
        return $row['c'];
    }
    function search($word, $offset, $limit) {
        $this->sjk->initSql('SELECT distinct uid FROM '.$this->mTableAttr.
                        " WHERE ".
                        " (`key`='login_name' AND `value` like #1)".
                        " OR (`key`='first_name' AND `value` like #1)".
                        " OR (`key`='first_name' AND `value` like #1)".
                        " OR (`key`='email' AND `value` like #1)".
                        " OR (`key`='host' AND `value` like #1)".
                        " LIMIT $offset,".($limit)
        );
        $this->sjk->setString(1, '%'.$word.'%');
        $rs=$this->sjk->query();
        $users=array();
        foreach ($rs as $row) {
            if (isset($users[$row['uid']])) {
                continue;
            }
            $users[$row['uid']]=$this->getByUid($row['uid']);
            $users[$row['uid']]['uid']=$row['uid'];
            //
        }
        return $users;
    }

    function getAll() {
        $this->sjk->initSql('SELECT uid FROM '.$this->mTable.' ORDER BY register_time');
        $rs=$this->sjk->query();
        $users=array();
        foreach ($rs as $row) {
            $users[]=$this->getByUid($row['uid']);
        }
        return $users;
    }
    function remove($uid) {
        $this->sjk->initSql('DELETE FROM '.$this->mTable.' WHERE uid=#1 LIMIT 1');
        $this->sjk->setInt(1, $uid);
        $this->sjk->query();
        $this->sjk->initSql('DELETE FROM '.$this->mTableAttr.' WHERE uid=#1');
        $this->sjk->setInt(1, $uid);
        $this->sjk->query();
    }

    function updatePassword($uid,$new_password) {
        $user=$this->getByUid($uid);
        $this->sjk->initSql('UPDATE '.$this->table.' SET pass=#1 WHERE uid=#2 LIMIT 1');
        $this->sjk->setString(1,self::digestPassword($new_password,$user['digestkey']));
        $this->sjk->setString(2,$uid);
        return $this->sjk->query();
    }
    static function digestPassword($password, $digestkey) {
        return pack('H32',md5(md5($password.$digestkey).$digestkey));
    }
    static function generatePassword() {
        return 
        chr(rand(97,122)).chr(rand(97,122)).chr(rand(97,122)).
        chr(rand(97,122)).chr(rand(97,122)).chr(rand(97,122));
    }
    static function generateDigestKey() {
        return 
        chr(rand(0,255)).chr(rand(0,255)).chr(rand(0,255)).
        chr(rand(0,255)).chr(rand(0,255)).chr(rand(0,255));
    }
}
/*
create table `cm_user`(
`uid` int unsigned auto_increment,
`pass` binary(16),
`digestkey` binary(6),
`register_time` int unsigned,
`register_ip` varbinary(39),
primary key(`uid`)
)ENGINE=MyISAM;

create table `cm_user_attr` (
`uid` int unsigned,
`key` varbinary(255),
`value`  varbinary(255),
PRIMARY KEY(`uid`,`key`)
)ENGINE=MyISAM;
*/
?>
